﻿using System;
using System.Collections.Generic;
using System.Text;

namespace JESAI.Core.Extensions
{
    /// <summary>
    /// 提供IfNullUse系列扩展方法
    /// </summary>
    public static class IfNullUseExtensions
    {
        #region 普通类的IfNullUse
        /// <summary>
        /// (obj??defaultValue)的简写形式，主要是为了解决连续调用时的括号问题，如下: 
        /// <code>var str=(obj??new object()).ToString()</code>
        /// <code>var str=obj.IfNullUse(new object()).ToString()</code>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T IfNullUse<T>(this T obj, T defaultValue = default) where T : class => obj ?? defaultValue;
        #endregion

        #region 数字的IfNullUse       

        #region 可空数字类型
        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static sbyte IfNullOrDefaultUse(this sbyte? obj, sbyte defaultValue = 0) => obj == null || obj == default(sbyte) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static byte IfNullOrDefaultUse(this byte? obj, byte defaultValue = 0) => obj == null || obj == default(byte) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ushort IfNullOrDefaultUse(this ushort? obj, ushort defaultValue = 0) => obj == null || obj == default(ushort) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static short IfNullOrDefaultUse(this short? obj, short defaultValue = 0) => obj == null || obj == default(short) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int IfNullOrDefaultUse(this int? obj, int defaultValue = 0) => obj == null || obj == default(int) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static uint IfNullOrDefaultUse(this uint? obj, uint defaultValue = 0) => obj == null || obj == default(uint) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long IfNullOrDefaultUse(this long? obj, long defaultValue = 0) => obj == null || obj == default(long) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ulong IfNullOrDefaultUse(this ulong? obj, ulong defaultValue = 0) => obj == null || obj == default(ulong) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static double IfNullOrDefaultUse(this double? obj, double defaultValue = 0) => obj == null || obj == default(double) ? defaultValue : obj.Value;

        /// <summary>
        /// 如果是null的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static decimal IfNullOrDefaultUse(this decimal? obj, decimal defaultValue = 0) => obj == null || obj == default(decimal) ? defaultValue : obj.Value;
        #endregion

        #region 非空数字类型
        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static sbyte IfDefaultUse(this sbyte obj, sbyte defaultValue = 0) => obj == default(sbyte) ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static byte IfDefaultUse(this byte obj, byte defaultValue = 0) => obj == default(byte) ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ushort IfDefaultUse(this ushort obj, ushort defaultValue = 0) => obj == default(ushort) ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static short IfDefaultUse(this short obj, short defaultValue = 0) => obj == default(short) ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int IfDefaultUse(this int obj, int defaultValue = 0) => obj == default ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static uint IfDefaultUse(this uint obj, uint defaultValue = 0) => obj == default ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long IfDefaultUse(this long obj, long defaultValue = 0) => obj == default ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ulong IfDefaultUse(this ulong obj, ulong defaultValue = 0) => obj == default ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static double IfDefaultUse(this double obj, double defaultValue = 0) => obj == default ? defaultValue : obj;

        /// <summary>
        /// 如果是默认值的话返回defaultValue
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static decimal IfDefaultUse(this decimal obj, decimal defaultValue = 0) => obj == default ? defaultValue : obj;
        #endregion

        #endregion

        #region 非数字类型的IfNullUse
        /// <summary>
        /// 如果是null的话返回defaultValue， (obj??defaultValue)的简写形式
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static bool IfNullUse(this bool? obj, bool defaultValue = false) => obj ?? defaultValue;
        #endregion

        #region 集合/数组/字典的IfNullUse 
        /// <summary>
        /// 如果集合为null则使用空元素集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static ICollection<T> IfNullUseNewList<T>(this ICollection<T> collection)
        {
            if (collection == null || collection.Count == 0) return new List<T>();
            return collection;
        }

        /// <summary>
        /// 如果数组为null则使用空元素数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="arr"></param>
        /// <returns></returns>
        public static T[] IfNullUseNewArray<T>(this T[] arr)
        {
            if (arr == null) return Array.Empty<T>();
            return arr;
        }

        /// <summary>
        /// 如果字典为null则使用空元素字典
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static Dictionary<TKey, TValue> IfNullUseNewDictinoary<TKey, TValue>(this Dictionary<TKey, TValue> dic)
        {
            if (dic == null) return new Dictionary<TKey, TValue>();
            return dic;
        }
        #endregion

        #region string 的IfNullUse
        /// <summary>
        /// 如果字符串为null或者空字符串,则使用备选值
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string IfNullOrEmptyUse(this string str, string defaultValue = default)
        {
            if (str == null || str.Length == 0) return defaultValue;
            return str;
        }
        #endregion
    }
}
